/*
 * @Description: 表格表单校验样式
 * @Author: James324
 * @Date: 2023-09-06 15:05:45
 * @LastEditors: James324
 * @LastEditTime: 2024-03-25 13:32:27
 */
import {
    getDom,
    getDomList,
    addErrorClass,
    removeErrorClass,
    Valid,
    StrategyKey,
    getColumnIndex,
    generateClassToId,
    validErrorMessage,
    isFunction
} from '@/utils';
import { isArray } from 'lodash-es';
import { TableRefs } from 'element-plus';
import type { BaseTableProps } from '../type';

/**
 * 校验样式相关逻辑
 */
export function useValidStyle(tableRef: Ref<TableRefs | null | undefined>) {
    /**
     * 获取表格所处行
     */
    const getTableRow = (el: HTMLElement) => {
        const elTableBody = getDomList('.el-table__body', el)![0];
        const elTableRow = getDomList('.el-table__row', elTableBody);

        return elTableRow;
    };

    /**
     * 获取表格所处列
     */
    const getTableColumn = (el: HTMLElement) => {
        if (el) {
            const elColumn = getDomList('.el-table__cell', el)!;
            return elColumn;
        }
        return [];
    };

    /**
     * 移除列校验
     */
    const resetColumnValid = (row: HTMLElement) => {
        getTableColumn(row).forEach((column: HTMLElement) => {
            const errDom = column.querySelector('.q-form-item__content') as HTMLElement;

            if (errDom) removeErrorClass(errDom!);
        });
    };

    /**
     * 移除所有校验
     */
    const resetAllValid = () => {
        const tableRows = getTableRow(tableRef.value!.$el)!;
        tableRows.forEach((row: HTMLElement) => {
            resetColumnValid(row);
        });
    };

    return {
        getTableRow,
        getTableColumn,
        resetAllValid
    };
}

/**
 * 校验文案相关逻辑
 */
interface Config {
    tableRef: Ref<TableRefs | null | undefined>;
    tableItems: any[];
}
export function useValidTable(props: BaseTableProps, tableData: Ref<any>, config: Config) {
    const errValidRef = ref();
    const { resetAllValid } = useValidStyle(config.tableRef);

    /**
     * 表格列配置项
     */
    const columnConfigs = config.tableItems;

    /**
     * 校验规则
     */
    const handleValidFieldPass = (row: any, rowIndex: number) => {
        const validTableData = isArray(row) ? row : null;
        const validData = validTableData
            ? validTableData
            : row
              ? [row]
              : props.cellEdit
                ? tableData.value.filter((item: any) => item.unAction) // 存在单元编辑需过滤出不是新增的数据
                : tableData.value;

        if (!validData.length) {
            errValidRef.value = {
                content: '表格数据不能为空，请添加表格数据'
            };
            return;
        }

        // 验证实例
        const validInput: any = new Valid();

        validData.forEach((data: any, index: number) => {
            for (const item of columnConfigs) {
                const validRuleIsArray = isArray(item.validRules); // 判断是否为数组类型

                if (item.validProps?.required) {
                    validInput.add(
                        {
                            value: data[item.modelKey!],
                            row: props.addTableRow
                                ? props.cellEdit
                                    ? index
                                    : getIndex(index)
                                : getIndex(index),
                            id: item.validProps.id, // 校验 id
                            dataId: data.id, // 当前数据 id
                            key: item.modelKey, // 当前校验 key
                            errMsgFn: validRuleIsArray ? null : item.validRules?.errMsgFn,
                            type: StrategyKey.IS_EMPTY
                        },
                        StrategyKey.IS_EMPTY,
                        '请完善必填信息'
                    );
                }

                if (validRuleIsArray) {
                    for (const valid of item.validRules) {
                        const { validType, errMsg } = valid as ValidRule;
                        validInput.add(
                            {
                                value: item.validValueFn
                                    ? item.validValueFn(
                                          config.tableRef.value?.data[index],
                                          item.modelKey
                                      )
                                    : data[item.modelKey!], // customValue 自定义校验值
                                row: props.addTableRow
                                    ? props.cellEdit
                                        ? index
                                        : getIndex(index)
                                    : getIndex(rowIndex ?? index), // rowIndex 如果为 null/undefined 则默认取 index
                                id: item.validProps?.id, // 校验 id
                                dataId: data.id, // 当前数据 id
                                key: item.modelKey, // 当前校验 key
                                tableInstance: config.tableRef.value,
                                type: validType,
                                ruleFn: valid.ruleFn,
                                errMsgFn: valid.errMsgFn,
                                validFn: {
                                    resetAllValid
                                }
                            },
                            validType,
                            errMsg
                        );
                    }
                }
            }
        });

        resetAllValid();

        errValidRef.value = validInput.start();

        if (errValidRef.value) {
            const { params, errMsg } = errValidRef.value;
            const className = generateClassToId(params.id);
            const domIndex =
                !props.lineEdit && !props.cellEdit
                    ? params.row
                    : getValidNumToEdit(tableData.value, params.dataId);
            const parentEl = getDom('.el-table__body', config.tableRef.value!.$el) || document;
            const element = getDomList(`.${className}`, parentEl as HTMLElement)?.[domIndex]; // .q-form-item__content

            if (element) addErrorClass(element!);

            // 获取当前校验项所处列号
            const columnIndex = getColumnIndex(config.tableItems, params.id as string);

            // 表格为新增模式并且单元编辑
            let actionNum;
            if (props.addTableRow && props.cellEdit) {
                const validData = tableData.value.filter(
                    (item: anyObj) => item.id === params.dataId
                )[0];

                if (validData && typeof validData === 'object') {
                    const errIndex = validData.unAction
                        ? tableData.value.findIndex(
                              (item: anyObj) => item.edit && item.unAction && !item[params.key]
                          )
                        : tableData.value.findIndex(
                              (item: anyObj) => item.edit && !item[params.key]
                          );

                    actionNum = errIndex + 1;
                }
            }

            setErrorText(params, errMsg, { columnIndex, actionNum });

            validErrorMessage(errMsg);
            return false;
        } else {
            return true;
        }
    };

    /**
     * 如果处于表格行内编辑，则过滤当前正在编辑的表格数据
     */
    const getValidNumToEdit = (tableData: any, id: string) => {
        const EditTableData = tableData.filter((item: any) => item.edit);
        return EditTableData.findIndex((data: any) => data.id === id);
    };

    /**
     * 转换索引
     */
    const getIndex = (index: number) => {
        if (index == null) index = 0;
        return index;
    };

    /**
     * 设置校验错误显示文案
     */
    interface Options {
        columnIndex: number;
        actionNum: number;
    }
    const setErrorText = (params: any, errMsg: string, { columnIndex, actionNum }: Options) => {
        let columnAddNum = 1;
        let rowNum = 0;
        if (!props.tableConfig.unIndex) columnAddNum++;
        if (!props.tableConfig.unSelection) columnAddNum++;

        const hasSlotName = columnConfigs.some(item => item.slotName);
        if (actionNum == null)
            rowNum = !props.addTableRow && hasSlotName ? params.row : params.row + 1;

        errValidRef.value.content = setErrTipContent(params, {
            errMsg,
            rowNum: actionNum ?? rowNum,
            columnIndex,
            columnAddNum
        }); // 设置校验文案提示内容
    };

    /**
     * 设置校验文案提示内容
     */
    const setErrTipContent = (params: any, ...args: any) => {
        const { type, errMsgFn } = params;
        const { rowNum, errMsg, columnIndex, columnAddNum } = args[0] || {};
        const columnNum = columnIndex + columnAddNum; // 校验错误列

        if (!props.addTableRow || params.row == null) {
            // 不是 table 表格可添加行模式或者自由编辑模式，或者当前行序号 params.row 为 null
            let errMsgText = errMsg;
            if (type !== StrategyKey.IS_EMPTY) {
                // 表单校验为空模式 || 自定义校验模式
                errMsgText = `您的输入有误，${errMsg}`;
            }

            return isFunction(errMsgFn) ? errMsgFn(rowNum, columnNum, errMsg) : errMsgText;
        } else {
            if (type === StrategyKey.IS_EMPTY) {
                // 表格项为必填项
                return `表格第 ${rowNum} 行第 ${columnNum} 列，${errMsg}`;
            } else if (type === StrategyKey.IS_CUSTOMIZE) {
                // 表格项为自定义校验
                return isFunction(errMsgFn)
                    ? errMsgFn(rowNum, columnNum, errMsg)
                    : `您在表格第 ${rowNum} 行第 ${columnNum} 列中输入有误，${errMsg}`;
            } else {
                return `您在表格第 ${rowNum} 行第 ${columnNum} 列中输入有误，${errMsg}`;
            }
        }
    };

    return {
        errValidRef,
        handleValidFieldPass
    };
}
